﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ViCode_LeVi.Data;
using ViCode_LeVi.Reports;
using System.IO;

namespace ViCode_LeVi.Controls
{
    /// <summary>
    /// Interaction logic for VMTabBalanceAndOthers_Balance.xaml
    /// </summary>
    public partial class VMTabBalanceAndOthers_Balance : UserControl
    {
        public VMTabBalanceAndOthers_Balance()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(VMTabBalanceAndOthers_Balance_Loaded);
            this.DataContextChanged += new DependencyPropertyChangedEventHandler(VMTabBalanceAndOthers_Balance_DataContextChanged);
        }

        void VMTabBalanceAndOthers_Balance_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            RefreshView();
        }

        private void RefreshView()
        {
            _balance = this.DataContext as Step_BalanceAndOthers_Balance;
            if (_balance != null)
            {
                GenUI(_balance);
                SetupButton_AddNew();
            }
        }
        Step_BalanceAndOthers_Balance _balance = null;
        void VMTabBalanceAndOthers_Balance_Loaded(object sender, RoutedEventArgs e)
        {
            RefreshView();
        }
        #region Gen
        private void GenUI(Step_BalanceAndOthers_Balance balance)
        {
            if (balance == null)
                return;
            if (balance.Items_KHACHHANG == null || balance.Items_KHACHHANG.Length == 0)
            {
                balance.AddNew(balance.GROUP_KHACHHANG_NAME);
            }
            GenUI(Panel_KhachHang, balance.Items_KHACHHANG);

            if (balance.Items_NHANVIEN == null || balance.Items_NHANVIEN.Length == 0)
            {
                balance.AddNew(balance.GROUP_NHANVIEN_NAME);
            }
            GenUI(Panel_NhanVien, balance.Items_NHANVIEN);

            if (balance.Items_SANXUAT == null || balance.Items_SANXUAT.Length == 0)
            {
                balance.AddNew(balance.GROUP_SANXUAT_NAME);
            }
            GenUI(Panel_SanXuat, balance.Items_SANXUAT);

            if (balance.Items_TAICHINH == null || balance.Items_TAICHINH.Length == 0)
            {
                balance.AddNew(balance.GROUP_TAICHINH_NAME);
            }
            GenUI(Panel_TaiChinh, balance.Items_TAICHINH);
        }
        private void GenUI(Panel panel, Step_BalanceAndOthers_Balance_Item[] items)
        {
            if (items == null || items.Length == 0)
            {
                panel.Children.Clear();
            }
            else
            {
                ////Collapse all
                //foreach(FrameworkElement child in panel.Children)
                //{
                //    child.Visibility = Visibility.Collapsed;
                //}
                //add
                var children = panel.Children.Cast<FrameworkElement>().ToArray();
                List<FrameworkElement> listInUI = new List<FrameworkElement>();
                foreach (var item in items)
                {
                    var child = children.FirstOrDefault(d => d.DataContext == item);
                    if (child == null)
                    {
                        child = new VMTabBalanceAndOthers_Balance_Item()
                        {
                            DataContext = item
                              ,
                            Action_Remove = (removeItem) =>
                              {
                                  if (_balance != null)
                                  {
                                      if (MessageBox.Show("Do you want to remove this item?", "Confirm", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
                                      {
                                          _balance.Remove(removeItem);
                                          removeItem.SendPropertyChanged_All();
                                          GenUI(_balance);
                                      }
                                  }
                              }
                        };
                        panel.Children.Add(child);
                    }
                    listInUI.Add(child);
                }
                //remove old
                List<FrameworkElement> listWillRemove = new List<FrameworkElement>();
                foreach (FrameworkElement child in panel.Children)
                {
                    if (!listInUI.Contains(child))
                        listWillRemove.Add(child);
                }
                foreach (var removeItem in listWillRemove)
                {
                    panel.Children.Remove(removeItem);
                }
            }
        }
        #endregion

        #region Button add new
        private void SetupButton_AddNew()
        {
            Button_AddNew_KhachHang.Click -= new RoutedEventHandler(Button_AddNew_KhachHang_Click);
            Button_AddNew_NhanVien.Click -= new RoutedEventHandler(Button_AddNew_NhanVien_Click);
            Button_AddNew_SanXuat.Click -= new RoutedEventHandler(Button_AddNew_SanXuat_Click);
            Button_AddNew_TaiChinh.Click -= new RoutedEventHandler(Button_AddNew_TaiChinh_Click);

            Button_AddNew_KhachHang.Click += new RoutedEventHandler(Button_AddNew_KhachHang_Click);
            Button_AddNew_NhanVien.Click += new RoutedEventHandler(Button_AddNew_NhanVien_Click);
            Button_AddNew_SanXuat.Click += new RoutedEventHandler(Button_AddNew_SanXuat_Click);
            Button_AddNew_TaiChinh.Click += new RoutedEventHandler(Button_AddNew_TaiChinh_Click);
        }

        void Button_AddNew_TaiChinh_Click(object sender, RoutedEventArgs e)
        {
            if (_balance != null)
                Button_AddNew(_balance.GROUP_TAICHINH_NAME);
        }

        void Button_AddNew_SanXuat_Click(object sender, RoutedEventArgs e)
        {
            if (_balance != null)
                Button_AddNew(_balance.GROUP_SANXUAT_NAME);
        }

        void Button_AddNew_NhanVien_Click(object sender, RoutedEventArgs e)
        {
            if (_balance != null)
                Button_AddNew(_balance.GROUP_NHANVIEN_NAME);
        }

        void Button_AddNew_KhachHang_Click(object sender, RoutedEventArgs e)
        {
            if (_balance != null)
                Button_AddNew(_balance.GROUP_KHACHHANG_NAME);
        }
        void Button_AddNew(string grpName)
        {
            if (_balance != null)
            {
                _balance.AddNew(grpName);
                GenUI(_balance);
            }
        }
        #endregion

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Report_BalancedScoreCards rep = new Report_BalancedScoreCards();
            var datasource = new List<Step_BalanceAndOthers_Balance>();
            datasource.Add(_balance);
            frmViewReport frm = new frmViewReport(rep, datasource);
            frm.Show();
        }

        private void Button_PrintUI_Click(object sender, RoutedEventArgs e)
        {

   //         PrintDialog printDlg = new PrintDialog();
   //         //chon may in neu can
   //         if (printDlg.ShowDialog() != true)
   //         { return; }

   //         this.Measure(new Size(printDlg.PrintableAreaWidth,
   //printDlg.PrintableAreaHeight));

   //         printDlg.PrintVisual(this, "User Control Printing.");
            
            Execute(this);

        }

        public void Execute(object parameter)
        {
            if (parameter is FrameworkElement)
            {
                FrameworkElement objectToPrint = parameter as FrameworkElement;
                PrintDialog printDialog = new PrintDialog();
                if ((bool)printDialog.ShowDialog().GetValueOrDefault())
                {
                    Mouse.OverrideCursor = Cursors.Wait;
                    System.Printing.PrintCapabilities capabilities = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket);
                    double dpiScale = 300.0 / 96.0;
                    FixedDocument document = new FixedDocument();
                    try
                    {
                        // Change the layout of the UI Control to match the width of the printer page
                        objectToPrint.Width = capabilities.PageImageableArea.ExtentWidth;
                        objectToPrint.UpdateLayout();
                        objectToPrint.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
                        Size size = new Size(capabilities.PageImageableArea.ExtentWidth, objectToPrint.DesiredSize.Height);
                        objectToPrint.Measure(size);
                        size = new Size(capabilities.PageImageableArea.ExtentWidth, objectToPrint.DesiredSize.Height);
                        objectToPrint.Measure(size);
                        objectToPrint.Arrange(new Rect(size));

                        // Convert the UI control into a bitmap at 300 dpi
                        double dpiX = 300;
                        double dpiY = 300;
                        RenderTargetBitmap bmp = new RenderTargetBitmap(Convert.ToInt32(capabilities.PageImageableArea.ExtentWidth * dpiScale), Convert.ToInt32(objectToPrint.ActualHeight * dpiScale), dpiX, dpiY, PixelFormats.Pbgra32);
                        bmp.Render(objectToPrint);

                        // Convert the RenderTargetBitmap into a bitmap we can more readily use
                        PngBitmapEncoder png = new PngBitmapEncoder();
                        png.Frames.Add(BitmapFrame.Create(bmp));
                        System.Drawing.Bitmap bmp2;
                        using (MemoryStream memoryStream = new MemoryStream())
                        {
                            png.Save(memoryStream);
                            bmp2 = new System.Drawing.Bitmap(memoryStream);
                        }
                        document.DocumentPaginator.PageSize = new Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight);

                        // break the bitmap down into pages
                        int pageBreak = 0;
                        int previousPageBreak = 0;
                        int pageHeight = Convert.ToInt32(capabilities.PageImageableArea.ExtentHeight * dpiScale);
                        while (pageBreak < bmp2.Height - pageHeight)
                        {
                            pageBreak += pageHeight;  // Where we thing the end of the page should be

                            // Keep moving up a row until we find a good place to break the page
                            while (!IsRowGoodBreakingPoint(bmp2, pageBreak))
                                pageBreak--;

                            PageContent pageContent = generatePageContent(bmp2, previousPageBreak, pageBreak, document.DocumentPaginator.PageSize.Width, document.DocumentPaginator.PageSize.Height, capabilities);
                            document.Pages.Add(pageContent);
                            previousPageBreak = pageBreak;
                        }

                        // Last Page
                        PageContent lastPageContent = generatePageContent(bmp2, previousPageBreak, bmp2.Height, document.DocumentPaginator.PageSize.Width, document.DocumentPaginator.PageSize.Height, capabilities);
                        document.Pages.Add(lastPageContent);
                    }
                    finally
                    {
                        // Scale UI control back to the original so we don't effect what is on the screen 
                        objectToPrint.Width = double.NaN;
                        objectToPrint.UpdateLayout();
                        objectToPrint.LayoutTransform = new ScaleTransform(1, 1);
                        Size size = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);
                        objectToPrint.Measure(size);
                        objectToPrint.Arrange(new Rect(new Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight), size));
                        Mouse.OverrideCursor = null;
                    }
                    printDialog.PrintDocument(document.DocumentPaginator, "Print Document Name");
                }
            }
        }

        private PageContent generatePageContent(System.Drawing.Bitmap bmp, int top, int bottom, double pageWidth, double PageHeight, System.Printing.PrintCapabilities capabilities)
        {
            FixedPage printDocumentPage = new FixedPage();
            printDocumentPage.Width = pageWidth;
            printDocumentPage.Height = PageHeight;

            int newImageHeight = bottom - top;
            System.Drawing.Bitmap bmpPage = bmp.Clone(new System.Drawing.Rectangle(0, top, bmp.Width, newImageHeight), System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            // Create a new bitmap for the contents of this page
            Image pageImage = new Image();
            BitmapSource bmpSource =
                System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                    bmpPage.GetHbitmap(),
                    IntPtr.Zero,
                    System.Windows.Int32Rect.Empty,
                    BitmapSizeOptions.FromWidthAndHeight(bmp.Width, newImageHeight));

            pageImage.Source = bmpSource;
            pageImage.VerticalAlignment = VerticalAlignment.Top;

            // Place the bitmap on the page
            printDocumentPage.Children.Add(pageImage);

            PageContent pageContent = new PageContent();
            ((System.Windows.Markup.IAddChild)pageContent).AddChild(printDocumentPage);

            FixedPage.SetLeft(pageImage, capabilities.PageImageableArea.OriginWidth);
            FixedPage.SetTop(pageImage, capabilities.PageImageableArea.OriginHeight);

            pageImage.Width = capabilities.PageImageableArea.ExtentWidth;
            pageImage.Height = capabilities.PageImageableArea.ExtentHeight;
            return pageContent;
        }

        private bool IsRowGoodBreakingPoint(System.Drawing.Bitmap bmp, int row)
        {
            double maxDeviationForEmptyLine = 1627500;
            bool goodBreakingPoint = false;

            if (rowPixelDeviation(bmp, row) < maxDeviationForEmptyLine)
                goodBreakingPoint = true;

            return goodBreakingPoint;
        }
         private double rowPixelDeviation(System.Drawing.Bitmap bmp, int row)
    {
        int count = 0;
        double total = 0;
        double totalVariance = 0;
        double standardDeviation = 0;
        System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
        int stride = bmpData.Stride;
        IntPtr firstPixelInImage = bmpData.Scan0;

        unsafe
        {
            byte* p = (byte*)(void*)firstPixelInImage;
            p += stride * row;  // find starting pixel of the specified row
            for (int column = 0; column < bmp.Width; column++)
            {
                count++;  //count the pixels

                byte blue = p[0];
                byte green = p[1];
                byte red = p[3];

                int pixelValue = System.Drawing.Color.FromArgb(0, red, green, blue).ToArgb();
                total += pixelValue;
                double average = total / count;
                totalVariance += Math.Pow(pixelValue - average, 2);
                standardDeviation = Math.Sqrt(totalVariance / count);

                // go to next pixel
                p += 3;
            }
        }
        bmp.UnlockBits(bmpData);

        return standardDeviation;
    }
}
    }

